package com.xtaller.lazy.api.base;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xtaller.lazy.base.TApi;
import com.xtaller.lazy.lib.R;
import com.xtaller.lazy.lib.annotation.Permission;
import com.xtaller.lazy.lib.annotation.Token;
import com.xtaller.lazy.lib.convert.J;
import com.xtaller.lazy.lib.convert.L;
import com.xtaller.lazy.lib.convert.M;
import com.xtaller.lazy.lib.convert.V;
import com.xtaller.lazy.model.base.Label;
import com.xtaller.lazy.model.base.LabelValue;
import com.xtaller.lazy.model.system.Dict;
import com.xtaller.lazy.parameter.DocLabel;
import com.xtaller.lazy.parameter.DocLabelValue;
import com.xtaller.lazy.service.base.LabelService;
import com.xtaller.lazy.service.base.LabelValueService;
import com.xtaller.lazy.service.system.DictService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.var;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @version V1.0
 * @author: Taller
 * @date: 2019-04-25
 * @Description: 画像标签api
 */
@Api(tags = "画像标签api")
@RestController
@RequestMapping("/v1/base")
public class LabelApi extends TApi {
    @Autowired private LabelService labelService;
    @Autowired private DictService dictService;
    @Autowired private LabelValueService valueService;

    private Map<String, String> baseVerify() {
        var verify = M.create("name", "画像标签名称不能为空")
                        .put("code", "画像标签编码不能为空");
        return verify;
    }

    @GetMapping("/labelByParent")
    @ApiOperation("读取字典数据")
    @Permission(authorities = "base-label-by-parent-id")
    public Object getSub(@ApiParam("页码") @RequestParam(value = "page", required = false, defaultValue = "1") int page,
                         @ApiParam("页长") @RequestParam(value = "limit", required = false, defaultValue = "50") int limit,
                         @ApiParam("页长") @RequestParam(value = "parentId", required = false, defaultValue = "-1") Long parentId){
        var p = new Page<Label>(page, limit);
        var qw = new QueryWrapper<Label>();
        qw.lambda().eq(Label::getParentId, parentId)
                .orderByDesc(Label::getOrderNumber);
        return p2t(labelService.page(p, qw));
    }

    @GetMapping("/label")
    @ApiOperation("读取数据")
    @Permission(authorities = "base-label-tree")
    public Object table(){
        var qw = new QueryWrapper<Label>();
        qw.lambda().orderByDesc(Label::getOrderNumber);
        var labels = labelService.list(qw);
        // 创建一条顶级数据
        if(labels.size() == 0){
            var label = new Label();
            label.setName("数据画像标签");
            label.setCode("data-label");
            label.setOrderNumber(999);
            label.setParentId(0L);
            labelService.save(label);
            labels = labelService.list(qw);
        }
        var list = formatLabel(labels);
        var data = J.create("list", list)
                    .put("tree", L.list2Tree(list, 0L));
        return R.ok(data);
    }

    @PostMapping("/label")
    @ApiOperation("创建")
    @Permission(authorities = "base-label-create")
    public Object create(@ApiParam("数据对象") @RequestBody DocLabel object){
        var check = V.checkEmpty(baseVerify(), object);
        if (check.getBoolean(CHECK)) {
            return R.error(check.getString(MESSAGE));
        }

        var qw = new QueryWrapper<Label>();
        qw.lambda().eq(Label::getCode, object.getCode());

        var labels = labelService.list(qw);
        if(labels.size() > 0){
            return R.error("画像标签编码必须是唯一值");
        }
        qw.lambda().eq(Label::getParentId, object.getParentId())
                .eq(Label::getName, object.getName());
        labels = labelService.list(qw);
        if(labels.size() > 0){
            return R.error("画像标签名称在同一级下必须是唯一值");
        }

        var model = J.o2m(object, Label.class);
        model.setCreateId(userId.get());
        model = labelService.model(model);
        if(model == null) {
            return R.error("数据创建失败");
        }
        return R.ok("数据创建成功", model);
    }

    @PutMapping("/label/{id}")
    @ApiOperation("修改数据")
    @Permission(authorities = "base-label-update")
    public Object update(@ApiParam("数据id") @PathVariable Long id,
                         @ApiParam("数据对象") @RequestBody DocLabel object){
        var model = labelService.getById(id);
        if(model == null) {
            return R.error("数据id异常");
        }

        var check = V.checkEmpty(baseVerify(), object);
        if (check.getBoolean(CHECK)) {
            return R.error(check.getString(MESSAGE));
        }

        var qw = new QueryWrapper<Label>();
        qw.lambda().eq(Label::getCode, object.getCode()).ne(Label::getId, id);

        var labels = labelService.list(qw);
        if(labels.size() > 0){
            return R.error("画像标签编码必须是唯一值");
        }
        qw.lambda().eq(Label::getParentId, object.getParentId())
                .eq(Label::getName, object.getName());
        labels = labelService.list(qw);
        if(labels.size() > 0){
            return R.error("画像标签名称在同一级下必须是唯一值");
        }

        model = J.o2m(object, Label.class);
        model.setId(id);
        model.setUpdateId(userId.get());

        model = labelService.model(model);
        if(model == null) {
            return R.error("数据修改失败");
        }else {
            return R.ok("数据修改成功", model);
        }
    }

    @DeleteMapping("/label/{id}")
    @ApiOperation("删除数据")
    @Permission(authorities = "base-label-delete")
    public Object delete(@ApiParam("数据id") @PathVariable Long id){
        var model = labelService.getById(id);
        if(model == null){
            return R.error("数据id异常");
        }
        if(model.getParentId().longValue() == 0L){
            return R.error("禁止删除顶层数据");
        }

        var dqw = new QueryWrapper<Label>();
        dqw.lambda().eq(Label::getParentId, id);
        var labels = labelService.list(dqw);
        if(labels.size() > 0){
            return R.error("该画像标签下有子数据信息禁止直接删除");
        }

        if(labelService.removeById(id)) {
            return R.ok("数据删除成功", J.create("id", id));
        }
        return R.error("数据删除失败");
    }

    @GetMapping("/label-template/{code}")
    @ApiOperation("根据code来读取画像标签模板")
    @Token
    public Object getLabelByCode(@PathVariable() String code){
        var qw = new QueryWrapper<Label>();
        qw.lambda().eq(Label::getCode, code)
                .eq(Label::getState, 1)
                .orderByDesc(Label::getOrderNumber);

        var model = labelService.getOne(qw);
        if(model == null){
            return R.ok(J.create());
        }
        // 处理数据
        qw = new QueryWrapper<Label>();
        qw.lambda().eq(Label::getParentId, model.getId())
                .eq(Label::getState, 1)
                .orderByDesc(Label::getOrderNumber);

        var data = labelService.list(qw);
        var list = J.list();
        data.stream().forEach(x -> {
            var obj = J.create("id", x.getId())
                    .put("name", x.getName())
                    .put("code", x.getCode())
                    .put("type", x.getType())
                    .put("dictCode", x.getDictCode())
                    .put("orderNumber", x.getOrderNumber())
                    .put("remark", x.getRemark())
                    .put("options", J.list());
            list.add(obj);
        });
        // 取出有字典的数据
        var dictCode = data.stream()
                .filter(x -> x.getDictCode().length() > 0)
                .map(x -> x.getDictCode())
                .collect(Collectors.toList());

        if(dictCode.size() > 0){
            var dictQw = new QueryWrapper<Dict>();
            dictQw.lambda().in(Dict::getCode, dictCode)
                    .orderByDesc(Dict::getOrderNumber);
            var parents = dictService.list(dictQw);
            var objects = J.list();
            if(parents.size() > 0){
                var dictParentIds = parents.stream().map(x -> x.getId()).collect(Collectors.toList());
                dictQw = new QueryWrapper<Dict>();
                dictQw.lambda().in(Dict::getParentId, dictParentIds)
                        .orderByDesc(Dict::getOrderNumber);
                var dicts = dictService.list(dictQw);
                if(dicts.size() > 0){
                    var opts = formatOption(dicts);

                    parents.stream().forEach(x -> {
                        opts.stream().filter(y -> y.get("parentId").equals(x.getId()))
                                .forEach(z -> {
                                    z.put("pcode", x.getCode());
                                    objects.add(z);
                                });
                    });
                }
            }
            if(objects.size() > 0){
                list.stream().forEach(x -> {
                   var opt = objects.stream().filter(y -> y.get("pcode").equals(x.get("dictCode"))).collect(Collectors.toList());
                    if(!opt.isEmpty()){
                        x.put("options", opt);
                    }
                });
            }
        }
        return R.ok(list);
    }

    /**
     * 绑定数据到options
     * */
    private List<JSONObject> getOptionsByCode(List<JSONObject> options, String code){
        var list = J.list();
        var opt = options.stream().filter(x -> x.getString("code").equals(code)).findFirst();
        if(opt.isPresent()){
            list = J.o2l(opt.get().get("options"));
        }
        return list;
    }




    /**
     * 格式化字典数据
     * */
    private List<JSONObject> formatOption(List<Dict> dicts){
        var list = J.list();
        dicts.stream().forEach(x -> {
            list.add(J.create("id", x.getId())
                    .put("text", x.getName())
                    .put("code", x.getCode())
                    .put("parentId", x.getParentId())
                    .put("sort", x.getOrderNumber()));
        });
        return list;
    }
    /*********************************画像标签***************************************/

    @PostMapping("/label-value/{dataId}")
    @ApiOperation("创建/修改画像标签数据")
    @Token
    public Object createLabelValue(
            @ApiParam("数据id") @PathVariable Long dataId,
            @ApiParam("数据") @RequestBody List<DocLabelValue> values){
        if(values.size() == 0){
            return R.error("至少提交一个数据");
        }
        List<LabelValue> lvs = new ArrayList<>();

        var qw = new QueryWrapper<LabelValue>();
        qw.lambda().eq(LabelValue::getDataId, dataId);

        // 检查旧数据
        var olds = valueService.list(qw);
        if(olds.size() == 0) {
            values.stream().forEach(x -> {
                var model = J.o2m(x, LabelValue.class);
                model.setDataId(dataId);
                model.setCreateId(userId.get());
                lvs.add(model);
            });
            valueService.saveBatch(lvs, lvs.size());
        }else{
            List<DocLabelValue> creates = new ArrayList<>();

            var labelIds1 = olds.stream().map(x -> x.getLabelId()).collect(Collectors.toList());
            var labelIds2 = values.stream().map(x -> x.getLabelId()).collect(Collectors.toList());
            // 找到删除的
            var delete = labelIds1.stream().filter(x -> !labelIds2.contains(x)).collect(Collectors.toList());
            // 找到新增的
            var create = labelIds2.stream().filter(x -> !labelIds1.contains(x)).collect(Collectors.toList());
            // 找到修改项
            Collection update = new ArrayList<>(labelIds1);
            Collection realB = new ArrayList<>(labelIds2);
            update.retainAll(realB);


            if(delete.size() > 0){
                var delQw = new QueryWrapper<LabelValue>();
                delQw.lambda().in(LabelValue::getLabelId, delete)
                        .eq(LabelValue::getDataId, dataId);
                // 删除前端不提交的标签
                // valueService.remove(delQw);
            }

            if(create.size() > 0){
                create.stream().forEach(x -> {
                    var opt = values.stream().filter(y -> x.equals(y.getLabelId())).findFirst();
                    if (opt.isPresent()){
                        creates.add(opt.get());
                    }
                });
                creates.stream().forEach(x -> {
                    var model = J.o2m(x, LabelValue.class);
                    model.setDataId(dataId);
                    model.setCreateId(userId.get());
                    lvs.add(model);
                });
                valueService.saveBatch(lvs, lvs.size());
            }

            if (update.size() > 0){
                update.stream().forEach(x -> {
                    var opt = olds.stream().filter(y -> y.getLabelId().equals(x)).findFirst();
                    if (opt.isPresent()){
                        var val = values.stream().filter(z -> z.getLabelId().equals(opt.get().getLabelId())).findFirst();
                        var model = opt.get();
                        if(!val.get().getValue().equals(model.getValue())) {
                            model.setValue(val.get().getValue());
                            valueService.model(model);
                        }
                    }
                });
            }
        }
        return R.ok("数据操作成功");
    }

}
